/**
 *  @file
 *  @brief   ShellSecMaterialConstant 壳截面等效材料刚度
 *  @author  wanghuan
 *  @date    2024.07.25
 *  @version v2.0
 *  @par Copyright(c):  ShenGong  Simulation corporation
 */

#pragma once
#include <map>

#include "Utility/Algebra/Matrix.h"

#include "DataStructure/Common/DataStructureNamespace.h"
#include "DataStructure/Common/Id.h"
#include "DataStructure/Common/Out.h"
#include "DataStructure/Common/Real.h"

SG_DATASTRUCTURE_FEM_NAMESPACE_OPEN
struct ShellSecMaterialConstant
{
    ShellSecMaterialConstant ();
    /** 判断单元是否具有拉-弯曲耦合项计算 */
    bool NeedCoupledItem () const;

    /** @brief 获取积分点处膜刚度
     * @param tGauss 高斯点处壳厚度值
     */
    void GetCm (SG::DataStructure::Common::Real tGauss, SG::Algebra::Matrix& Cm) const;
    void GetCb (SG::DataStructure::Common::Real tGauss, SG::Algebra::Matrix& Cb) const;
    void GetCs (SG::DataStructure::Common::Real tGauss, SG::Algebra::Matrix& Cs) const;
    void GetCd (SG::DataStructure::Common::Real tGauss, SG::Algebra::Matrix& Cd) const;

    /**
     * @brief   : 获得壳节点某点的面密度
     * @param   : tGauss  高斯点处厚度，对复合材料截面，此参数无效。
     * @return  :
     * @author  : wanghuan
     * @date    : 2024.11.19
     */
    SG::DataStructure::Common::Real GetArealDensity (SG::DataStructure::Common::Real tGauss) const;

    SG::DataStructure::Common::Id   m_pId;           ///< 属性参数
    SG::Algebra::Matrix             m_Cm;            ///< 3*3 膜部分材料刚度
    SG::Algebra::Matrix             m_Cb;            ///< 3*3 弯曲部分材料刚度
    SG::Algebra::Matrix             m_Cs;            ///< 2*2 剪切部分材料刚度
    SG::Algebra::Matrix             m_Cd;            ///< 膜和弯曲耦合部分材料刚度
    SG::DataStructure::Common::Real m_t;             ///< 截面厚度
    SG::DataStructure::Common::Real m_nsm;           ///< 单位面积非结构质量
    SG::DataStructure::Common::Real m_arealDensity;  //< 复合材料面密度，普通材料储存密度
    bool                            m_isComposite;
    bool                            m_purePlate;     ///< shell.mat1Id 为空，单元为纯板
    bool                            m_pureMembrane;  ///< pshell.mid2为空，单元为纯膜
};

inline ShellSecMaterialConstant::ShellSecMaterialConstant ()
    : m_Cm (3, 3), m_Cb (3, 3), m_Cs (2, 2), m_Cd (3, 3), m_t (0.0), m_arealDensity (0.0), m_isComposite{ false }, m_purePlate{ false },
      m_pureMembrane{ false }
{}

/** @brief 拉弯耦合项是否需要计算
 *
 */
inline bool ShellSecMaterialConstant::NeedCoupledItem () const
{
    auto row = m_Cd.GetRowSize ();
    auto col = m_Cd.GetColSize ();
    for (std::size_t i = 0; i < row; ++i)
    {
        for (std::size_t j = 0; j < col; ++j)
        {
            if (fabs (m_Cd (i, j)) > 1e-12)
            {
                return true;
            }
        }
    }

    return false;
}

inline void ShellSecMaterialConstant::GetCm (SG::DataStructure::Common::Real tGauss, SG::Algebra::Matrix& _OUT Cm) const
{
    if (m_isComposite)
        Cm = m_Cm;
    else
        Cm = m_Cm * tGauss;
}

inline void ShellSecMaterialConstant::GetCb (SG::DataStructure::Common::Real tGauss, SG::Algebra::Matrix& Cb) const
{
    if (m_isComposite)
        Cb = m_Cb;
    else
        Cb = m_Cb * (tGauss * tGauss * tGauss);
}

inline void ShellSecMaterialConstant::GetCs (SG::DataStructure::Common::Real tGauss, SG::Algebra::Matrix& Cs) const
{
    if (m_isComposite)
        Cs = m_Cs;
    else
        Cs = m_Cs * tGauss;
}

/**
 * @brief   : 拉弯耦合部分等效材料刚度 （该功能目前只支持PCOMP的拉弯耦合）
 *
 *            Pshell只支持各向同性材料，此时 m_Cd所有元素为 0.0
 * @param   : tGauss    积分点厚度， 对于复合材料，此处tGauss设为1.0，后续Pshell增加其他材料支持此接口需检查正确性
 * @param[out]   : Cd   返回材料弹性刚度的值
 */
inline void ShellSecMaterialConstant::GetCd (SG::DataStructure::Common::Real tGauss, SG::Algebra::Matrix& Cd) const
{
    if (m_isComposite)
        Cd = m_Cd;
    else
        Cd = m_Cd * tGauss;
}

inline SG::DataStructure::Common::Real ShellSecMaterialConstant::GetArealDensity (SG::DataStructure::Common::Real tGauss) const
{
    if (m_isComposite)
        return m_arealDensity;

    // 普通截面
    return m_arealDensity * tGauss;
}

using ShellSecMaterialConstantTable = std::map<SG::DataStructure::Common::Id, ShellSecMaterialConstant>;

/**
 * @brief   : 材料刚度坐标转换矩阵
 * @param   : cos, sin   转轴角度方向
 * @param   :  转轴角度，单位弧度
 * @param   : T1     弯曲材料刚度的转换矩阵
 * @param   : T2     剪切材料刚度的转换矩阵
 * @return  :
 * @author  : wanghuan
 * @date    : 2024.11.13
 */
DECLSPEC void calcMatCoordTransMatrix (const SG::DataStructure::Common::Real cos,
                                       const SG::DataStructure::Common::Real sin,
                                       SG::Algebra::Matrix& _OUT             T1,
                                       SG::Algebra::Matrix& _OUT             T2);

SG_DATASTRUCTURE_FEM_NAMESPACE_CLOSE